/*-------------------------------------------------------------------------------
* file:     app_uart.c
* brief:    application
* copyright Copyright (C) 2020-2022 @ NanoIC
* Date:     2022-08-15
* Version:  V1.00
* Author:   
*-------------------------------------------------------------------------------*/


/* include ----------------------------------------------------------------*/
#include "app_uart.h"
#include "one_wire_bus_app.h"
#include "app_init.h"
/* externs function--------------------------------------------------------*/
extern void uart_timer_tick_0_1ms_handler(csp_uart_t *ptUartBase,uint8_t byIdx);

/* externs variablesr------------------------------------------------------*/
extern uint8_t app_stop_wait_flag;
extern volatile bool global_hall_weak_up_intrupt_flag;

/* Private variablesr------------------------------------------------------*/
csi_uart_config_t tUartConfig;                                  /* UART 参数配置结构体 */
ringbuffer_t g_tRingbuf;

uint8_t uart_tx_buffer[APP_UART_TX_PHY_BUF_SIZE];               /* 发送缓冲区 */	
uint8_t uart_rx_buffer[APP_UART_RX_PHY_BUF_SIZE + 4];           /* 接收缓冲区 */
uint8_t backup_uart_rx_buffer[APP_UART_RX_PHY_BUF_SIZE + 4];    /* 备份接收缓冲区数据，用于命令处理 */
uint8_t backup_uart_rx_head[APP_UART_RX_HEAD_BACK_SIZE];        /* 头信息缓冲区，防止连续的两帧串口数据冲掉前面字节 */

bool uart_0ms5_timer_flag;                  /* 500us时基标志位 */
uint8_t uart_0ms5_timer_tick;               /* 时基计时tick */
uint32_t uart_100us_timer_tick;               /* 时基计时tick */
uint32_t syn_100us_timer_tick; 

bool uart_4ms_timer_flag;                  /* 4ms时基标志位 */
uint8_t uart_4ms_timer_tick;               /* 时基计时tick */

bool uart_500ms_timer_flag;                  /* 500ms时基标志位 */
uint32_t uart_500ms_timer_tick;               /* 时基计时tick */

uint32_t handshake_ack_tick=0;

bool send_ack_flag;
uint32_t test_tick;
uint32_t sleep_tick=0;

bool f_uart_rec_one_frame;                  /* 接收到一帧数据的标志 */
uint16_t uart_rx_length;                    /* 接收数据长度 */
volatile uint8_t release_tx_flag;

static uint16_t global_tx_send_length	  = 0;			//串口TX发送长度


/* Private function--------------------------------------------------------*/

/**
 * @brief 用于uart tx引脚配置或释放的函数
 * 
 * @param is_trans: true 配置uart tx引脚； false 引脚释放
 */
void app_uart_tx_io_set(bool is_trans)
{
//     return;
    if(is_trans)
    {
        csi_pin_set_mux(UART_TX, UART_TX_UART);		//TX
//		csi_pin_set_mux(UART_RX, UART_RX_INPUT);		
    }
    else
    {
        //设置TX为高阻态 
        csi_pin_set_mux(UART_TX,PB00_INPUT);
//		csi_pin_set_mux(UART_RX, UART_RX_UART);		
    }
}

void app_uart_doze_tx_io_set(bool is_trans)
{
//     return;
    if(is_trans)
    {
        csi_pin_set_mux(UART_TX, UART_TX_UART);		//TX
		csi_pin_set_mux(UART_RX, UART_RX_INPUT);		//TX
//		csi_pin_pull_mode(UART_TX,GPIO_PULLUP); 
    }
    else
    {
        //设置TX为高阻态 
        csi_pin_set_mux(UART_TX,PB00_INPUT);
		csi_pin_set_mux(UART_RX, UART_RX_UART);		//TX
//		csi_pin_pull_mode(UART_TX,GPIO_PULLNONE);     
    }
}

/**
 * @brief : 串口上电初始化函数
 *      UART2:
 *          PB0.1 UART2 RX
 *          PB0.0 UART2 TX
 */
void app_uart_init(void)
{
	uart_100us_timer_tick=0;
    uart_0ms5_timer_tick = 0x00;
    uart_0ms5_timer_flag = false;
	
    uart_4ms_timer_tick = 0x00;
    uart_4ms_timer_flag = false;
	
	uart_500ms_timer_tick= 0x00;                  
	uart_500ms_timer_flag= false;

    uart_rx_length = 0;
    f_uart_rec_one_frame = false;
    
    app_uart_init_io_set();
    csi_uart_set_buffer(UART_BASE, &g_tRingbuf, uart_rx_buffer, sizeof(uart_rx_buffer));

    tUartConfig.byParity = UART_PARITY_NONE;		// 校验位，奇校验
    tUartConfig.wBaudRate = UART_ONE_WIRE_BAUDRATE;					// 波特率 460800
    tUartConfig.wInt = UART_INTSRC_RXFIFO
                        | UART_INTSRC_RXFIFO_OV
                        | UART_INTSRC_TXDONE;
    tUartConfig.byTxMode = UART_TX_MODE_POLL;	//发送 轮询模式
    tUartConfig.byRxMode = UART_RX_MODE_INT_DYN;  //接收 interrupt模式

    csi_uart_init(UART_BASE, &tUartConfig);			//初始化串口
    csi_uart_recv_timeout(UART_BASE, 88, DISABLE);//UART接收超时时间，单位：bit位周期，8个bytes(11bit*8=88, 115200波特率时=764us)
    csi_uart_int_enable(UART_BASE, UART_INTSRC_RXTO,ENABLE);

    csi_vic_set_prio((int32_t)UART_IRQ_NUM, 0);
    csi_uart_start(UART_BASE, UART_FUNC_RX_TX);		// 开启UART的RX和TX功能，也可单独开启RX或者TX功能	
    csi_etb_init();								// 使能ETB模块	
    csi_uart_dma_tx_init(UART_BASE, DMA_CH1, ETB_CH10);
    csi_vic_set_prio((int32_t)DMA_IRQ_NUM, 0);
}

/**
 * @brief 用于uart trx引脚配置
 * 
 */
void app_uart_init_io_set(void)
{
    csi_pin_set_mux(UART_TX, UART_TX_UART);     // TX
    csi_pin_set_mux(UART_RX, UART_RX_UART);     // RX
    csi_pin_pull_mode(UART_RX,GPIO_PULLNONE);     // RX管脚上拉使能, 建议配置
	
	csi_pin_pull_mode(UART_TX,GPIO_PULLNONE);  
	csi_pin_drive(UART_TX,1);  
//	csi_pin_output_mode(UART_TX,GPIO_OPEN_DRAIN);
    app_uart_tx_io_set(false);
    release_tx_flag = 0;
	

#if POWER_SAVING_ENABLE
    csi_pin_irq_mode(UART_RX, EXI_GRP16, GPIO_IRQ_FALLING_EDGE);        // RX PB01 下降沿产生中断，选择中断组16
    csi_pin_irq_enable(UART_RX, EXI_GRP16, ENABLE);                     // RX PB01 中断组16使能
    csi_vic_set_prio((int32_t)EXI0_IRQ_NUM, 2);
    csi_vic_set_wakeup_irq(EXI0_IRQ_NUM);
#endif
}

/**
 * @brief : 串口接收超时处理函数
 * 
 * @param byIdx: 串口号
 * @param rx_len: 接收到数据长度
 * @return 
 */
void app_uart_rx_timerout_callback(uint8_t byIdx,uint16_t rx_len)
{
    uint16_t i;
    if(byIdx == UART_IDX)
    {
        for(i=0;i<APP_UART_RX_HEAD_BACK_SIZE;i++)
        {
            backup_uart_rx_head[i] = uart_rx_buffer[i];
        }
        if(rx_len >= 4)
        {  // 收到一帧数据
            uart_rx_length = rx_len;
            f_uart_rec_one_frame = true;  // rec timerout
        }
    }
}

/**
 * @brief 单总线计时时基
 * 
 */
void app_uart_timer_tick_0_1ms_handler(void)
{
    uart_timer_tick_0_1ms_handler(UART_BASE, UART_IDX);
	uart_100us_timer_tick++;
    uart_0ms5_timer_tick ++;
	syn_100us_timer_tick++;
	handshake_ack_tick++;
	

	test_tick++;
	sleep_tick++;
	if(uart_0ms5_timer_tick >= UART_SCAN_TIMER_N)  // 500us
    {
        uart_0ms5_timer_tick = 0;
        uart_0ms5_timer_flag = true;
    }
	
	if(uart_4ms_timer_flag)
	{
		 uart_4ms_timer_tick = 0;
	}else{
		uart_4ms_timer_tick++;
		if(uart_4ms_timer_tick >= 40)  // 500us
		{
			uart_4ms_timer_flag = true;
			uart_4ms_timer_tick = 0;
		}
	}

	uart_500ms_timer_tick++;
	if(uart_500ms_timer_tick >= 5000)  // 500us
	{
		uart_500ms_timer_flag = true;
		uart_500ms_timer_tick = 0;
	}

}

/**
 * @brief 获取0.5mS时间标志，并清除
 * 
 * @return : true(是) false(否)
 */
static bool app_uart_0ms5_flag_get_and_clear(void)
{
    uint32_t irq_reg;
    bool flag;

    irq_reg = csi_irq_save();
    flag = uart_0ms5_timer_flag;
    uart_0ms5_timer_flag = false;
    csi_irq_restore(irq_reg);

    return flag;
}

/**
 * @brief : 串口是否接收到一帧数据,并清除标志
 * 
 * @return : true(是) false(否)
 */
static bool app_uart_rec_flag_get_and_clear(void)
{
    uint32_t irq_reg;
    bool flag;

    irq_reg = csi_irq_save();
    flag = f_uart_rec_one_frame;
    f_uart_rec_one_frame = false;
    csi_irq_restore(irq_reg);
    return flag;
}

/**
 * @brief : 串口接收一帧数据长度
 * 
 * @return : tuint16_t(长度)
 */
static uint16_t app_uart_rec_length(void)
{
    uint32_t irq_reg;
    uint16_t len;

    irq_reg = csi_irq_save();
    len = uart_rx_length;
    csi_irq_restore(irq_reg);
    return len;
}


/**
 * @brief : 向串口发送一帧数据
 * 
 * @param pbuf 数据缓存指针
 * @param len  数据长度
 * @return true 发送成功
 * @return false 发送失败
 */
bool one_wire_bus_uart_send_one_packet(uint8_t * pbuf,uint16_t len)
{
    uint16_t i;
    if(len > APP_UART_TX_PHY_BUF_SIZE || release_tx_flag == 1)
    {
        return false;
    }
    for(i=0;i<len;i++)
    {
        uart_tx_buffer[i] = pbuf[i];
    }
    app_uart_tx_io_set(true);
	//global_tx_send_delay_flag = true;
    if(csi_uart_send_dma(UART_BASE, DMA_CH1, (void *)uart_tx_buffer, len) != CSI_OK)
    {
//       app_uart_tx_io_set(false);
    }	
    return true;
}

/**
 * @brief : 串口发送完处理函数
 * 
 * @param byIdx: 串口号
 * @return 
 */
void app_uart_tx_done_callback(uint8_t byIdx)
{
    release_tx_flag = 0x01;
}

extern  void app_uart_tx_io_set(bool is_trans);
/**
 * @brief : 串口处理进程
 */
void app_uart_process(void)
{
    uint16_t i;
    bool f_rec_frame,f_0ms5;

    if(release_tx_flag == 0x01)
    {
        release_tx_flag = 0;
        app_uart_tx_io_set(false);
		uart_500ms_timer_tick = 0;
		uart_500ms_timer_flag=false;
    }
    f_rec_frame = app_uart_rec_flag_get_and_clear();
    if(f_rec_frame)
    {
        uint16_t rec_len;
        /*
         * 1. 串口接收到一帧数据; 
         * 2. 对数据进行校验、解码处理；
         * 3. 将应答包填入相应队列；
         */
        rec_len = app_uart_rec_length();
        for(i=0;i<APP_UART_RX_HEAD_BACK_SIZE;i++)
        {
            backup_uart_rx_buffer[i] = backup_uart_rx_head[i];
        }
        if(rec_len > APP_UART_RX_HEAD_BACK_SIZE)
        {
            for(i=APP_UART_RX_HEAD_BACK_SIZE;i<rec_len;i++)
            {
                backup_uart_rx_buffer[i] = uart_rx_buffer[i];
            }
        }
        #if APP_UART_DEBUG_LIG
        if(backup_uart_rx_buffer[6] != 0x3f && backup_uart_rx_buffer[6] != 0x01 &&
                backup_uart_rx_buffer[6] != 0x02 && backup_uart_rx_buffer[6] != 0x03)
        {
                printf("updata = ");
                console_log_num_byte(backup_uart_rx_buffer,rec_len);
        } 
        #endif
        one_wire_bus_app_rec_callback(backup_uart_rx_buffer,rec_len);
		uart_4ms_timer_tick = 0;
        uart_4ms_timer_flag = false;
		//uart_500ms_timer_tick = 0;
    }
	
	if(uart_500ms_timer_flag)
	{
		uart_500ms_timer_flag=false;
		one_wire_bus_app_timer_tick_callback_500ms();
		
	}
	

    f_0ms5 = app_uart_0ms5_flag_get_and_clear();
    if(f_0ms5)
    {
        /*
         *  1. 0.5mS调用一次；
         *  2. 主要用于维护单总线时间片时序；
         *  3. 完成数据的发送和重传；
         */

		one_wire_bus_app_timer_tick_callback_0ms5();
		
        
    }


}

/** \brief gpio interrupt handle function
 * 
 *  \param[in] byExiNum: exi interrupt vector num, 0~4
 *  \return none
 */ 
void gpio_irqhandler(uint8_t byExiNum)
{
    volatile uint32_t wExiSta; 
    wExiSta = csp_exi_get_port_irq(SYSCON);

    if((byExiNum == 0)&&(wExiSta == (0x01ul << EXI_GRP16)))
    {
        app_stop_wait_flag = 1;//关闭wait，避免uart rx数据错误
    }
	
//	if((byExiNum == 4)&&(wExiSta == (0x01ul << EXI_GRP10)))
//    {
//        app_tp_wake_flag = 1;//关闭wait，避免uart rx数据错误
//    }
	
    if(byExiNum == 4 && wExiSta == STATUS_EXI14)
    {
      
    }
    
    csp_exi_clr_port_irq(SYSCON,wExiSta);		//clear interrput 
}


/**
 * @brief disable gpio irq
 * 
 */
void app_uart_wake_exi_disable(void)
{	
    csi_pin_irq_enable(UART_RX, EXI_GRP16, DISABLE);
    csi_vic_clear_wakeup_irq(EXI0_IRQ_NUM);
}

/**
 * @brief 休眠唤醒切换
 * 
 */
void app_uart_sleep_and_weakup_io_set(bool on)
{
    if(on)
    {	
        //唤醒
        app_uart_wake_exi_disable();
        app_uart_init();
//		app_uart_init_io_set();
//		csi_uart_start(UART_BASE, UART_FUNC_RX_TX);		// 开启UART的RX和TX功能，也可单独开启RX或者TX功能	
    }
    else
    {
        //休眠
        //设置TX为高阻态 
        csi_uart_stop(UART_BASE, UART_FUNC_RX_TX);
//        csi_pin_set_mux(UART_TX,PB00_GPD);                     
//        csi_pin_pull_mode(UART_TX, GPIO_PULLDOWN);  
		csi_pin_drive(UART_TX,0);             
		csi_pin_set_mux(UART_TX,PB00_OUTPUT);  
		csi_gpio_port_set_low(GPIOB0, (0x01ul << 0));
		
        //设置RX唤醒
        csi_pin_set_mux(UART_RX,UART_RX_INPUT);                         //PB01 输入
        csi_pin_pull_mode(UART_RX, GPIO_PULLNONE);                        //PB01 下拉	
        csi_pin_irq_mode(UART_RX, EXI_GRP16, GPIO_IRQ_RISING_EDGE);    //RX PB01 上升沿产生中断，选择中断组16
        csi_pin_irq_enable(UART_RX, EXI_GRP16, ENABLE);                 //RX PB01 中断组16使能
        // csi_vic_set_prio((int32_t)EXI0_IRQ_NUM, 2);
        csi_vic_set_wakeup_irq(EXI0_IRQ_NUM);
    }
}


/**
 * @brief 休眠唤醒切换
 * 
 */
void app_uart_doze_and_weakup_io_set(bool on)
{
    if(on)
    {	
        //唤醒
        app_uart_wake_exi_disable();
		release_tx_flag = 0;
//		csi_uart_start(UART_BASE, UART_FUNC_TX);		// 开启UART的RX和TX功能，也可单独开启RX或者TX功能
    }
    else
    {
        //休眠
        //设置TX为高阻态 
        csi_uart_stop(UART_BASE, UART_FUNC_RX);
        csi_pin_set_mux(UART_TX,PB00_GPD);                     
        csi_pin_pull_mode(UART_TX, GPIO_PULLNONE);  
//		csi_pin_drive(UART_TX,0); 
		
        //设置RX唤醒
        csi_pin_set_mux(UART_RX,UART_RX_INPUT);                         //PB01 输入
        csi_pin_pull_mode(UART_RX, GPIO_PULLNONE);                        //PB01 下拉	
        csi_pin_irq_mode(UART_RX, EXI_GRP16, GPIO_IRQ_RISING_EDGE);    //RX PB01 下降沿产生中断，选择中断组16
        csi_pin_irq_enable(UART_RX, EXI_GRP16, ENABLE);                 //RX PB01 中断组16使能
        // csi_vic_set_prio((int32_t)EXI0_IRQ_NUM, 2);
        csi_vic_set_wakeup_irq(EXI0_IRQ_NUM);
    }
}
